﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using JelloPhysics;
using Microsoft.Xna.Framework;

namespace CJC.Silverlight.JelloPhysicsDemo
{
	public partial class Page : UserControl
	{
		private World world = new World();
		private Random rand = new Random();
		private Brush borderBrush = new SolidColorBrush( Colors.Black );
		private List<Body> staticBodies = new List<Body>();

		public Page()
		{
			InitializeComponent();
			StartTimer();
		}

		private void Storyboard_Completed( object sender, EventArgs e )
		{
			var width = LayoutRoot.ActualWidth;
			var height = LayoutRoot.ActualHeight;

			if ( width > 0 && height > 0 )
			{
				if ( staticBodies.Count < 1 ) CreatePlatforms();

				for ( int i = 0; i < 6; i++ ) world.update( 1 / 120f );

				var removed = new List<Body>();

				foreach ( var body in world )
				{
					var shape = body.ObjectTag as Polygon;

					if ( shape == null )
					{
						shape = new Polygon();
						shape.Fill = new SolidColorBrush( Color.FromArgb( 50, (byte)rand.Next( 255 ), (byte)rand.Next( 255 ), (byte)rand.Next( 255 ) ) );
						shape.StrokeThickness = 4;
						shape.Stroke = borderBrush;
						LayoutRoot.Children.Add( shape );
						body.ObjectTag = shape;
					}

					var points = new PointCollection();
					var visible = false;
					var scale = height / 50;

					foreach ( var pm in body )
					{
						var x = ( width / 2 ) + ( pm.Position.X * scale );
						var y = ( height / 2 ) - ( pm.Position.Y * scale );

						if ( x >= 0 && x < width && y >= 0 && y < height ) visible = true;

						points.Add( new Point( x, y ) );
					}

					shape.Points = points;

					if ( !visible ) removed.Add( body );
				}

				foreach ( var body in removed )
				{
					world.removeBody( body );
					LayoutRoot.Children.Remove( body.ObjectTag as Shape );
				}
			}

			StartTimer();
		}

		private void StartTimer()
		{
			( Resources[ "frameTimer" ] as Storyboard ).Begin();
		}

		private void CreatePlatforms()
		{
			foreach ( var body in staticBodies )
			{
				world.removeBody( body );
				LayoutRoot.Children.Remove( body.ObjectTag as Shape );
			}

			var scale = LayoutRoot.ActualHeight / 10;
			var halfScale = scale / 2;

			for ( int index = 0; index < 10; ++index )
			{
				var width = (float)( 3f + ( rand.NextDouble() * 10 ) );

				// static ground object.
				var groundShape = new ClosedShape();
				groundShape.begin();
				groundShape.addVertex( new Vector2( -width, -1f ) );
				groundShape.addVertex( new Vector2( -width, 1f ) );
				groundShape.addVertex( new Vector2( width, 1f ) );
				groundShape.addVertex( new Vector2( width, -1f ) );
				groundShape.finish();

				// make the body.
				var groundBody = new Body(
					world,
					groundShape,
					float.PositiveInfinity,
					new Vector2( (float)( ( rand.NextDouble() * scale) - halfScale ), (float)( ( rand.NextDouble() * scale * 0.75 ) - halfScale - 5 ) ),
					(float)( ( rand.NextDouble() * Math.PI / 8 ) - ( Math.PI / 16 ) ),
					Vector2.One,
					false );

				staticBodies.Add( groundBody );
			}

			Storyboard_Completed( this, EventArgs.Empty );
		}

		private void DropBalloon( object sender, RoutedEventArgs e )
		{
			var shape = new ClosedShape();
			shape.begin();

			for ( var rad = 0d; rad < Math.PI * 2; rad += Math.PI / 10 )
			{
				shape.addVertex( new Vector2( (float)Math.Sin( rad ), (float)Math.Cos( rad ) /** 0.75f*/ ) );
			}

/*			shape.addVertex( new Vector2( -1.0f, 0f ) );
			shape.addVertex( new Vector2( 0f, 1.0f ) );
			shape.addVertex( new Vector2( 1.0f, 0f ) );
			shape.addVertex( new Vector2( 0f, -1.0f ) );*/
			shape.finish();

			var scale = LayoutRoot.ActualHeight / 50;
			var itemScale = (float)( 1f + ( 2f * rand.NextDouble() ) );
/*
			var body = new FallingBody( world, shape, 1f, 40f, 1500f, 20f, 1500f, 20f,
				new Vector2( 0, 20 ), MathHelper.ToRadians( new Random().Next( 360 ) ), new Vector2( itemScale ) );
*/
			var body = new FallingBody( world, shape, 1f, 40f, 100f, 10f, 100f, 10f,
				new Vector2( (float)( ( rand.NextDouble() * scale ) - ( scale / 2 ) ), 20 ),
				MathHelper.ToRadians( new Random().Next( 360 ) ),
				new Vector2( itemScale ) );

			var count = shape.Vertices.Count;

			for ( int index = 0; index < count; ++index )
			{
				body.addInternalSpring( index, ( index + 4 ) % count, 400f, 12f );
			}

//			body.addInternalSpring( 1, 3, 400f, 12f );
		}

		private void MovePlatforms( object sender, RoutedEventArgs e )
		{
			CreatePlatforms();
		}
	}
}
